]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
magnifier: Scale the sprite to match the current monitor scaling
authorMarco Trevisan (Treviño) <mail@3v1n0.net>
Wed, 27 Mar 2019 15:14:39 +0000 (16:14 +0100)
committerFlorian Müllner <fmuellner@gnome.org>
Fri, 1 Aug 2025 14:29:38 +0000 (16:29 +0200)
Compute the sprite texture scale (unfortunately using a workaround, based on
mutter cursor size preferences, tying to figure out the closest texture integer
scaling), and use this value to compute the scaling that should be applied to
the sprite in order to match the current monitor scaling.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/475>
(cherry picked from commit 484928e80acb4b6d161dcdd50d48e7731b4f9bee)

js/ui/layout.js
js/ui/magnifier.js

index 4a60403bf3bc88272de70fe5437678dd6c0d14ec..a66f65b1e871f642d103c0657b07ece96675609a 100644 (file)
@@ -992,22 +992,38 @@ export const LayoutManager = GObject.registerClass({
         return ws.get_work_area_for_monitor(monitorIndex);
     }
 
+    _findIndexForRect(x, y, width, height) {
+        const rect = new Mtk.Rectangle({
+            x: Math.floor(x),
+            y: Math.floor(y),
+            width: Math.ceil(x + width) - Math.floor(x),
+            height: Math.ceil(y + height) - Math.floor(y),
+        });
+        return global.display.get_monitor_index_for_rect(rect);
+    }
+
     // This call guarantees that we return some monitor to simplify usage of it
     // In practice all tracked actors should be visible on some monitor anyway
     findIndexForActor(actor) {
         let [x, y] = actor.get_transformed_position();
         let [w, h] = actor.get_transformed_size();
-        const rect = new Mtk.Rectangle({x, y, width: w, height: h});
-        return global.display.get_monitor_index_for_rect(rect);
+        return this._findIndexForRect(x, y, w, h);
     }
 
-    findMonitorForActor(actor) {
-        let index = this.findIndexForActor(actor);
+    _findMonitorForIndex(index) {
         if (index >= 0 && index < this.monitors.length)
             return this.monitors[index];
         return null;
     }
 
+    findMonitorForActor(actor) {
+        return this._findMonitorForIndex(this.findIndexForActor(actor));
+    }
+
+    findMonitorForPoint(x, y) {
+        return this._findMonitorForIndex(this._findIndexForRect(x, y, 1, 1));
+    }
+
     _queueUpdateRegions() {
         if (!this._updateRegionIdle) {
             const laters = global.compositor.get_laters();
index 3b5c011a7b39048aeffa9594cea10e6a7fa30f68..1620a704628339a7fd997ce8fbf9e1e2683380ad 100644 (file)
@@ -5,6 +5,7 @@ import GDesktopEnums from 'gi://GDesktopEnums';
 import Gio from 'gi://Gio';
 import GLib from 'gi://GLib';
 import GObject from 'gi://GObject';
+import Meta from 'gi://Meta';
 import Shell from 'gi://Shell';
 import St from 'gi://St';
 import * as Signals from '../misc/signals.js';
@@ -49,6 +50,8 @@ const MouseSpriteContent = GObject.registerClass({
 }, class MouseSpriteContent extends GObject.Object {
     _init() {
         super._init();
+        this._scale = 1.0;
+        this._monitorScale = 1.0;
         this._texture = null;
     }
 
@@ -56,7 +59,10 @@ const MouseSpriteContent = GObject.registerClass({
         if (!this._texture)
             return [false, 0, 0];
 
-        return [true, this._texture.get_width(), this._texture.get_height()];
+        let width = this._texture.get_width() / this._scale;
+        let height = this._texture.get_height() / this._scale;
+
+        return [true, width, height];
     }
 
     vfunc_paint_content(actor, node, _paintContext) {
@@ -72,6 +78,29 @@ const MouseSpriteContent = GObject.registerClass({
         textureNode.add_rectangle(actor.get_content_box());
     }
 
+    _textureScale() {
+        if (!this._texture)
+            return 1;
+
+        /* This is a workaround to guess the sprite scale; while it works fine
+         * in normal scenarios, it's not guaranteed to work in all the cases,
+         * and so we should actually add an API to mutter that will allow us
+         * to know the real sprite texture scaling in order to adapt it to the
+         * wanted one. */
+        let avgSize = (this._texture.get_width() + this._texture.get_height()) / 2;
+        return Math.max(1, Math.floor(avgSize / Meta.prefs_get_cursor_size() + .1));
+    }
+
+    _recomputeScale() {
+        let scale = this._textureScale() / this._monitorScale;
+
+        if (this._scale !== scale) {
+            this._scale = scale;
+            return true;
+        }
+        return false;
+    }
+
     get texture() {
         return this._texture;
     }
@@ -86,7 +115,15 @@ const MouseSpriteContent = GObject.registerClass({
 
         if (!oldTexture || !coglTexture ||
             oldTexture.get_width() !== coglTexture.get_width() ||
-            oldTexture.get_height() !== coglTexture.get_height())
+            oldTexture.get_height() !== coglTexture.get_height()) {
+            this._recomputeScale();
+            this.invalidate_size();
+        }
+    }
+
+    set monitorScale(monitorScale) {
+        this._monitorScale = monitorScale;
+        if (this._recomputeScale())
             this.invalidate_size();
     }
 });
@@ -119,6 +156,8 @@ export class Magnifier extends Signals.EventEmitter {
         this._settingsInit(aZoomRegion);
         aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
 
+        this._updateContentScale();
+
         St.Settings.get().connect('notify::magnifier-active', () => {
             this.setActive(St.Settings.get().magnifier_active);
         });
@@ -127,6 +166,13 @@ export class Magnifier extends Signals.EventEmitter {
         this._cursorUnfocusInhibited = false;
     }
 
+    _updateContentScale() {
+        let monitor = Main.layoutManager.findMonitorForPoint(this.xMouse,
+            this.yMouse);
+        this._mouseSprite.content.monitorScale = monitor
+            ? monitor.geometry_scale : 1;
+    }
+
     /**
      * showSystemCursor:
      * Show the system mouse pointer.
@@ -268,6 +314,8 @@ export class Magnifier extends Signals.EventEmitter {
         this.xMouse = xMouse;
         this.yMouse = yMouse;
 
+        this._updateContentScale();
+
         let sysMouseOverAny = false;
         this._zoomRegions.forEach(zoomRegion => {
             if (zoomRegion.scrollToMousePos())